package com.design.pattern.proxy.dynamic.jdk;

import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author : 翌擎科技
 * @date : 2022/9/20 21:45
 */
@Slf4j
public class SubjectInvocationHandler implements InvocationHandler {


    private Object subject;

    public SubjectInvocationHandler(Object subject){
        this.subject=subject;
    }

    /**
     * @param clazz 代理对象的class
     * @param <T> 创建的代理对象
     * @return 代理对象
     *过Proxy的newProxyInstance方法来创建我们的代理对象，我们来看看其三个参数
     * ClassLoader loader： ClassLoader对象来加载我们的代理对象
     * Class<?>[] interfaces, 我们这里为代理对象提供的接口是真实对象所实行的接口，表示我要代理的是该真实对象，这样我就能调用这组接口中的方法了
     * InvocationHandler h,我们这里将这个代理对象关联到了上方的 InvocationHandler 这个对象上
     */
    public <T> T getInstance(Class<T> clazz){
        return (T) Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Proxy Before：JDK代理前添加自己操作");
        log.info("proxy={},method={},args={},subject={}",proxy,method,args,subject);
        // 当代理对象调用真实对象的方法时，其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
        Object invoke = method.invoke(subject, args);
        System.out.println("Proxy Before：JDK代理前添加自己操作!");
        log.info("invoke",invoke);
        return invoke;
    }
}
